﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using SingleUserMall.Common;
using SingleUserMall.Orders;
using SingleUserMall.Refunds.Form;
using SingleUserMall.Refunds.VO;
using SingleUserMall.Stores;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Domain.Uow;

namespace SingleUserMall.Refunds
{
    [AbpAuthorize]
    public class RefundManageAppService : SingleUserMallAppServiceBase, IRefundManageAppService
    {
        private readonly IRepository<Refund, long> _refundRepository;
        private readonly IRepository<OrderDetail, long> _orderDetailRepository;
        private readonly IRepository<RefundLog, long> _refundLogRepository;
        private readonly IRepository<Store, int> _storeRepository;
        public RefundManageAppService(
            IRepository<Refund, long> refundRepository,
            IRepository<OrderDetail, long> orderDetailRepository,
            IRepository<RefundLog, long> refundLogRepository,
            IRepository<Store, int> storeRepository
            )
        {
            _refundRepository = refundRepository;
            _orderDetailRepository = orderDetailRepository;
            _refundLogRepository = refundLogRepository;
            _storeRepository = storeRepository;
        }

        public async Task<RefundVO> GetRefundAsync(SingleId<long> form)
        {
            var refund = await _refundRepository.FirstOrDefaultAsync(form.Id);
            return refund.ToVO<Refund, RefundVO>((r, vo) =>
            {
                vo.inOrder = r.Order;
                vo.inItem = r.OrderDetail.ItemSpec.Item;
                vo.inItemSpec = r.OrderDetail.ItemSpec;
                vo.inOrderDetail = r.OrderDetail;
            });
        }

        public async Task<PagedResultDto<RefundVO>> GetRefundAppliesAsync(RefundSearchForm form)
        {
            var userId = AbpSession.GetUserId();
            bool isAdmin = await UserManager.CheckAdminAndPlatformRole(userId);

            var query = _refundRepository.GetAll().Where(x => x.Status == RefundStatus.WaitAudit)
                .WhereIf(form.BeginTime.HasValue, x => DbFunctions.TruncateTime(x.CreationTime) >= DbFunctions.TruncateTime(form.BeginTime))
                .WhereIf(form.EndTime.HasValue, x => DbFunctions.TruncateTime(x.CreationTime) <= DbFunctions.TruncateTime(form.EndTime))
                .OrderByDescending(x => x.CreationTime);


            if(!isAdmin)
            {
                var store = _storeRepository.FirstOrDefault(x => x.UserId == userId);
                query = (from s in query
                         join b in _orderDetailRepository.GetAll() on s.OrderId equals b.OrderId
                         where b.ItemSpec.Item.StoreId == store.Id
                         select s).OrderByDescending(x => x.CreationTime);
            }

            return await query.ToPagedResultDtoAsync<Refund, RefundVO>(form, (r, vo) =>
             {
                 vo.inOrder = r.Order;
                 vo.inItem = r.OrderDetail.ItemSpec.Item;
                 vo.inItemSpec = r.OrderDetail.ItemSpec;
                 vo.inOrderDetail = r.OrderDetail;
             });
        }

        public async Task<PagedResultDto<RefundVO>> GetRefundHistoriesAsync(RefundHistorySearchForm form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                var userId = AbpSession.GetUserId();
                bool isAdmin = await UserManager.CheckAdminAndPlatformRole(userId);
                var query = _refundRepository.GetAll().Where(x => x.Status > RefundStatus.WaitAudit)
                    .WhereIf(form.BeginTime.HasValue, x => DbFunctions.TruncateTime(x.CreationTime) >= DbFunctions.TruncateTime(form.BeginTime))
                    .WhereIf(form.EndTime.HasValue, x => DbFunctions.TruncateTime(x.CreationTime) <= DbFunctions.TruncateTime(form.EndTime))
                    .WhereIf(form.Status.HasValue, x => x.Status == form.Status)
                    .OrderByDescending(x => x.CreationTime);

                if (!isAdmin)
                {
                    var store = _storeRepository.FirstOrDefault(x => x.UserId == userId);
                    query = (from s in query
                        join b in _orderDetailRepository.GetAll() on s.OrderId equals b.OrderId
                        where b.ItemSpec.Item.StoreId == store.Id
                        select s).OrderByDescending(x => x.CreationTime);
                }

                return await query.ToPagedResultDtoAsync<Refund, RefundVO>(form, (r, vo) =>
                {
                    vo.inOrder = r.Order;
                    vo.inItem = r.OrderDetail.ItemSpec.Item;
                    vo.inItemSpec = r.OrderDetail.ItemSpec;
                    vo.inOrderDetail = r.OrderDetail;
                });
            }
        }

        public async Task PassAsync(AuditForm form)
        {
            var userId = AbpSession.GetUserId();
            var refund = await _refundRepository.FirstOrDefaultAsync(form.Id);
            if (refund.Status == RefundStatus.WaitAudit)
            {
                refund.Status = RefundStatus.Audited;
                refund.CloseReason = form.Reason;
                refund.RefundTime = DateTime.Now;
                var order = refund.Order;
                OrderManager.Refund(order,refund);
                await _refundLogRepository.InsertAsync(new RefundLog
                {
                    RefundId = refund.Id,
                    UserId = userId,
                    Content = $"审核通过，审核意见：{form.Reason}",
                    IsSeller = false
                });
            }
        }

        public async Task RejectAsync(AuditForm form)
        {
            var userId = AbpSession.GetUserId();
            var refund = await _refundRepository.FirstOrDefaultAsync(form.Id);
            if (refund.Status == RefundStatus.WaitAudit)
            {
                refund.Status = RefundStatus.Rejected;
                refund.CloseReason = form.Reason;
                refund.RefundTime = DateTime.Now;
                await _refundLogRepository.InsertAsync(new RefundLog
                {
                    RefundId = refund.Id,
                    UserId = userId,
                    Content = $"审核驳回，审核意见：{form.Reason}",
                    IsSeller = false
                });
            }
        }
    }
}
